/**
* This function handles all client related functions and interacts with client.
*/

//-------------------------------------------------------
// Comments & File Logging
//-------------------------------------------------------
/**
* @author Soon
* @date 26th January 2014
* TODO: Replace "Please input the " with a MACRO like ECE244
*/

//-------------------------------------------------------
// Header Files
//-------------------------------------------------------
#include <errno.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h> // for EXIT_FAILURE
#include "storage.h" // Defines max len for inputs
#include "shared.h" // setupTime()

//-------------------------------------------------------
// Constants
//-------------------------------------------------------
#define SERVERHOST "localhost"
#define SERVERPORT 1376
#define SERVERUSERNAME "admin"
#define SERVERPASSWORD "dog4sale"
#define TABLE "marks"
#define KEY "ece297"
#define LOGGING 2
enum {Connect = 1, Authenticate = 2, Get = 3, Set = 4, Disconnect = 5, Exit = 6};
char inputstr[] ="Please input the";

//-------------------------------------------------------
// Main
//-------------------------------------------------------

/**
* Main function initializes the client
*/
int main(int argc, char *argv[])
{
     // Set up time for logging
    char dateS[5], hourS[5], monthS[5], minS[5], secS[5];
    int year;
    // Get the current time and store into strings
    setupTime(&dateS, &hourS, &monthS, &minS, &secS, &year);
    char fileName[MAX_STRTYPE_SIZE];
    sprintf(fileName,"Client-%d-%s-%s-%s-%s-%s.log", year, monthS, dateS, hourS, minS, secS );
    int logChoice = LOGGING;
    switch(logChoice)
    {
	case 0: // Disable Logging
	    fileClient = NULL;
	    break;
	case 1: // Log to stdout
	    fileClient = stdout;
	    break;
	case 2: // Log to File
	    // Append file for appending an update
	    fileClient = fopen (fileName,"a+");
	    if (fileClient == NULL)
	    {
		printf("Error opening file.\n");
		exit(EXIT_FAILURE);
	    }
	    break;
    }
    // Variables
    char username[MAX_USERNAME_LEN], password[MAX_ENC_PASSWORD_LEN],
	 hostname[MAX_HOST_LEN], port[MAX_PORT_LEN],
	 table[MAX_TABLE_LEN], key[MAX_KEY_LEN];
    int portNum = 0;
    int choice = 0;
    int status;
    void *conn;
    struct storage_record r;
    // Client Interface
    while(1)
    {
	// Displaying a menu
	printf("---------------------\n 1) Connect\n 2) Authenticate\n 3) Get\n 4) Set\n 5) Disconnect\n 6) Exit\n---------------------\n");
	printf("Please enter your selection: ");
	scanf("%d", &choice);
	// Handling garbage inputs (non-numbers)
	int c;
	while((c = getchar()) != EOF)
    		if (c == '\n')
        		break;
	// @note: This will be an error if user did not enter a number
	//	  in scanf, it is fxed with the above code that
	//	  empties the stdin buffer
	switch(choice)
	{
	    //-----------------------------------------
	     case Connect:
	    //------------------------------------------
		printf("%s hostname: ", inputstr);
		scanf("%s", &hostname);
		printf("%s port: ", inputstr);
		scanf("%s", &port);
		portNum = atoi(port);
		// Connect to server, conn points to sockfd returned
		conn = storage_connect(hostname, portNum);
		if(!conn)
		{
		    sprintf(message, "Cannot connect to server @ %s:%d. Error code: %d.\n", hostname, portNum, errno);
		    printf("%s", message);
		    logger(fileClient, message);
		    return -1;
	    	}
		break;
	    //------------------------------------------
	    case Authenticate:
	    //------------------------------------------
		printf("%s username: ", inputstr);
		scanf("%s", &username);
		printf("%s password: ", inputstr);
		scanf("%s", &password);
	    	// Authenticate the client, sends an authenticated message out to server
	    	status = storage_auth(username, password, conn);
	    	if(status != 0)
	    	{
		    sprintf(message, "storage_auth failed with username '%s' and password '%s'. " \
		   "Error code: %d.\n", username, password, errno);
		    printf("%s", message);
		    logger(fileClient, message);
		    storage_disconnect(conn);
		    return status;
	    	}
	    	// Client prints storage_auth: successful
	    	sprintf(message, "storage_auth: successful.\n");
		printf("%s", message);
		logger(fileClient, message);
		break;
	    //------------------------------------------
	    case Get:
	    //------------------------------------------
		printf("%s key: ", inputstr);
		scanf("%s", &key);
		printf("%s table: ", inputstr);
		scanf("%s", &table);
	 	// Issue storage_get and print message to server
		// and changes value of r from "some_value" to "GET marks ece297"
		status = storage_get(TABLE, KEY, &r, conn);
		if(status != 0)
		{
		    sprintf(message, "storage_get failed. Error code: %d.\n", errno);
		    printf("%s", message);
		    logger(fileClient, message);
		    storage_disconnect(conn);
		    return status;
		}
		sprintf(message, "storage_get: the value returned for key '%s' is '%s'.\n", KEY, r.value);
		printf("%s", message);
		logger(fileClient, message);
		break;
	    //------------------------------------------
	    case Set:
	    //------------------------------------------
		printf("%s key: ", inputstr);
		scanf("%s", &key);
		printf("%s the table: ", inputstr);
		scanf("%s", &table);
		// Create a storage_record r that stores
		// Issue storage_set to store a value with its associated key
		// Copies some_value onto r.value
		// with the maximum char to copy as sizeof r.value
		strncpy(r.value, "some_value", sizeof r.value);
		// Currently just prints out to screen that it has set storage
		status = storage_set(TABLE, KEY, &r, conn);
		if(status != 0)
		{
		    sprintf(message, "storage_set failed. Error code: %d.\n", errno);
		    printf("%s", message);
		    logger(fileClient, message);
		    storage_disconnect(conn);
		    return status;
		}
		sprintf(message, "storage_set: successful.\n");
		printf("%s", message);
		logger(fileClient, message);
		break;
	    //------------------------------------------
	    case Disconnect:
	    //------------------------------------------
		// Disconnect from server
		status = storage_disconnect(conn);
		if(status != 0)
		{
		    sprintf(message, "storage_disconnect failed. Error code: %d.\n", errno);
		    printf("%s", message);
		    logger(fileClient, message);
		    return status;
		}
		break;
	    //------------------------------------------
	    case Exit:
	    //------------------------------------------
	        // Exit the client
		return 0;
		break;
	    //------------------------------------------
	    default: // Invalid Input
	    //------------------------------------------
		printf("Please enter a valid selection\n");
		break;
	}
    }
}
